package com.qipay.api.alipay.controller.v1;

import com.alipay.api.internal.util.AlipaySignature;
import com.qipay.baas.model.AlipayTransferLog;
import com.qipay.baas.model.Order;
import com.qipay.baas.model.Sp;
import com.qipay.order.config.OrderStateEnum;
import com.qipay.order.service.OrderService;
import com.qipay.pay.AlipayTransferService;
import com.qipay.pay.AlipayWapService;
import com.qipay.pay.WeiXinPayService;
import com.qipay.pay.entity.CpPayAlipayTransferRequest;
import com.qipay.pay.entity.SpPayWeiXinNativeCallbackRequest;
import com.qipay.sp.SpConfigService;
import com.qipay.sp.SpService;
import com.qipay.utils.RequestUtils;
import com.qipay.utils.SignSortMD5Utils;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.Map;

@RestController
@RequestMapping("/callback/alipay/v1")
public class AlipayCallbackController {

    protected final Logger logger = LoggerFactory.getLogger(getClass());

    private static final String SIGN_KEY = "sign";
    private static final String SP_CONFIG_KEY_SECRET = "rsa_public_key_alipay";

    @Autowired
    WeiXinPayService weiXinPayService;
    @Autowired
    OrderService orderService;

    @Autowired
    SpService spService;

    @Autowired
    SpConfigService spConfigService;

    @Autowired
    AlipayWapService alipayWapService;
    @Autowired
    AlipayTransferService alipayTransferService;

    @RequestMapping(value = "/wap", method = RequestMethod.POST, produces = {"application/xml;charset=UTF-8"})
    private String unionCreate(
            HttpServletRequest request,
            HttpServletResponse response
    ) throws Exception {
        Map<String,String> params = RequestUtils.getRequestParams(request);
        logger.info("request from " + request.getRequestURI() + ", request body:" + params);

        String tradeStatus = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"),"UTF-8");

        if(!(tradeStatus.equals("TRADE_SUCCESS") || tradeStatus.equals("TRADE_FINISHED"))) {
            logger.error("支付宝支付回调trade_status错误" + params);
            return buildReturnStr("fail");
        }

        SpPayWeiXinNativeCallbackRequest bean = convertToBean(params);

        Order order = orderService.getByTradeNo(bean.getOutTradeNo());
        if (order == null) {
            return buildReturnStr("fail");
        }
        Sp sp = spService.get(order.getSpId().intValue());

        String rsaPublicKey = spConfigService.getValue(order.getSpId(), AlipayCallbackController.SP_CONFIG_KEY_SECRET);
        boolean verify_result = AlipaySignature.rsaCheckV1(params, rsaPublicKey, "UTF-8", "RSA2");
        if(!verify_result){
            logger.info("验签失败");
            return buildReturnStr("fail");
        }
        if(order.getState()== OrderStateEnum.SUCCESS.getType()){
            return buildReturnStr("SUCCESS");
        }
        try {
            bean.setFeeType("CNY");
            bean.setNonceStr(RandomStringUtils.randomNumeric(32));
            weiXinPayService.payWeixinNativeCallback(bean);
            //单笔转账功能
            if(!StringUtils.isEmpty(sp.getZfbNo())){
                CpPayAlipayTransferRequest cpPayAlipayTransferRequest = new CpPayAlipayTransferRequest();
                BeanUtils.copyProperties(order,cpPayAlipayTransferRequest);
                //转账要传真实的支付金额
                cpPayAlipayTransferRequest.setAmount(order.getActualPayAmount()-
                        new BigDecimal(order.getActualPayAmount()).multiply(new BigDecimal("5.5")).divide(
                                new BigDecimal(1000),0,
                                BigDecimal.ROUND_UP).intValue());
                cpPayAlipayTransferRequest.setZfbNo(sp.getZfbNo());
                Map<String, Object> result = alipayTransferService.transfer(cpPayAlipayTransferRequest);
                if(!"0".equals(result.get("result_code"))){
                    //支付宝余额支付功能被关闭
                    //关闭该支付通道，并提示警告信息
                    AlipayTransferLog alipayTransferLog = (AlipayTransferLog) result.get("alipayTransferLog");
                    sp.setState((byte)1);
                    sp.setFailReason("余额支付功能关闭");
                    spService.update(sp);
                }else{
                    return buildReturnStr("SUCCESS");
                }
            }

        } catch (Exception ex) {
            logger.error("回调报错：" + ex.getMessage());
        }

        return buildReturnStr("fail");
    }

    @RequestMapping(value = "/sync", method = RequestMethod.GET, produces = {"application/xml;charset=UTF-8"})
    private ModelAndView sync(
            HttpServletRequest request,
            HttpServletResponse response
    ) throws Exception {
        ModelAndView modelAndView = new ModelAndView("/pay/success_script");
        return modelAndView;
    }
    @RequestMapping(value = "/from", method = RequestMethod.GET, produces = {"application/xml;charset=UTF-8"})
    private ModelAndView from(
            HttpServletRequest request,
            HttpServletResponse response
    ) throws Exception {
        ModelAndView modelAndView = new ModelAndView("/pay/cancel_script");
        return modelAndView;
    }

    private SpPayWeiXinNativeCallbackRequest convertToBean(Map<String, String> params) {
        SpPayWeiXinNativeCallbackRequest request = new SpPayWeiXinNativeCallbackRequest();

        if ("TRADE_SUCCESS".equals(params.get("trade_status"))) {
            request.setStatus(0);
            request.setResultCode(0);
            request.setPayResult(0);
        } else {
            request.setStatus(1);
            request.setResultCode(1);
            request.setPayResult(1);
        }

        if (params.get("app_id") != null)
            request.setMchId(params.get("app_id").toString());

        if (params.get("nonce_str") != null)
            request.setNonceStr(params.get("nonce_str").toString());

        if (params.get("sign") != null)
            request.setSign(params.get("sign").toString());

        if (params.get("trade_no") != null)
            request.setTransactionId(params.get("trade_no").toString());

        if (params.get("out_trade_no") != null)
            request.setOutTradeNo(params.get("out_trade_no").toString());

        if (params.get("time_end") != null)
            request.setTimeEnd(params.get("time_end").toString());

        if (params.get("total_amount") != null)
            request.setTotalFee(new BigDecimal(params.get("total_amount").toString()).multiply(new BigDecimal(String.valueOf(100))).intValue());

        if (params.get("out_transaction_id") != null)
            request.setOutTransactionId(params.get("out_transaction_id").toString());

        if (params.get("fee_type") != null)
            request.setFeeType(params.get("fee_type").toString());

        return request;
    }

    private String buildReturnStr(String return_code) {
        return return_code;
    }

    public static void main(String[] args) {
        String result = "charset=UTF-8&fee_type=CNY&mch_id=1000081&nonce_str=1514537873113&out_trade_no=HC293779829751D&pay_result=0&result_code=0&sign_type=MD5&status=0&time_end=2017-12-29 16:57:53&total_fee=1&trade_type=NET&transaction_id=1514537798513a0&version=1.0&key=588dda3c12d2486eafb16b1818f3da1d";
//
        String result0 = DigestUtils.md5Hex(result).toUpperCase();
        System.out.println(result0);
    }
}
